from PIL import Image, ImageDraw, ImageFont
import numpy as np
import os

class NeedlePrinter:
    def __init__(self, template_path='模板.png'):
        """初始化拟针式打印机模拟器"""
        self.template_path = template_path
        self.image = None
        self.draw = None
        self.load_template()
        
    def load_template(self):
        """加载模板图片"""
        if not os.path.exists(self.template_path):
            raise FileNotFoundError(f"模板图片不存在: {self.template_path}")
        self.image = Image.open(self.template_path).convert('RGBA')
        self.draw = ImageDraw.Draw(self.image)
        print(f"已加载模板图片: {self.template_path}")
        self.get_template_size()  # 自动显示模板尺寸信息
        
    def get_template_size(self):
        """获取并打印模板图片的尺寸信息"""
        if self.image:
            width, height = self.image.size
            print(f"模板图片尺寸: 宽度={width}px, 高度={height}px")
            return width, height
        else:
            print("模板图片尚未加载")
            return None, None
    

    
    def add_text(self, text, position, font_size=12, color=(0, 0, 0), opacity=255, bold=False, faded=True):
        """
        在图片上添加拟针式打印机风格的文字
        
        参数:
        - text: 要添加的文字内容
        - position: 文字的位置坐标 (x, y)
        - font_size: 文字大小
        - color: 文字颜色，默认黑色 (RGB格式)
        - opacity: 文字透明度，0-255，默认255（完全不透明）
        - bold: 是否加粗，默认不加粗
        - faded: 是否添加消失效果，默认True
        """
        # 尝试加载两种字体：宋体(中文)和黑体(英文)
        try:
            simsun_font = ImageFont.truetype("simsun.ttc", font_size)
        except IOError:
            simsun_font = ImageFont.load_default()
        
        try:
            simhei_font = ImageFont.truetype("simhei.ttf", font_size)  # 黑体字体用于英文和数字
        except IOError:
            simhei_font = simsun_font  # 如果无法加载黑体，使用宋体替代
        
        # 定义一个内部函数来处理中文和英文混合的文本
        def _draw_mixed_text(text, pos, color, bold):
            import re
            # 定义中文字符的正则表达式
            chinese_pattern = re.compile(r'[\u4e00-\u9fa5]')
            english_pattern = re.compile(r'[a-zA-Z0-9]')
            
            current_x, current_y = pos
            i = 0
            while i < len(text):
                char = text[i]
                # 处理中文字符
                if chinese_pattern.match(char):
                    # 计算连续中文字符的长度
                    chinese_end = i
                    while chinese_end < len(text) and chinese_pattern.match(text[chinese_end]):
                        chinese_end += 1
                    chinese_text = text[i:chinese_end]
                    # 绘制中文
                    if faded:
                        # 为中文创建临时图像以应用消失效果
                        _draw_char_with_faded_effect(chinese_text, (current_x, current_y), simsun_font, color, bold)
                    else:
                        self._draw_dot_matrix_text(chinese_text, (current_x, current_y), simsun_font, color, bold)
                    # 更新x坐标
                    w, _ = self.draw.textbbox((0, 0), chinese_text, font=simsun_font)[2:4]
                    current_x += w
                    i = chinese_end
                # 处理英文字符和数字
                elif english_pattern.match(char):
                    # 计算连续英文字符的长度
                    english_end = i
                    while english_end < len(text) and english_pattern.match(text[english_end]):
                        english_end += 1
                    english_text = text[i:english_end]
                    # 绘制英文
                    if faded:
                        # 为英文创建临时图像以应用消失效果
                        _draw_char_with_faded_effect(english_text, (current_x, current_y), simhei_font, color, bold)
                    else:
                        self._draw_dot_matrix_text(english_text, (current_x, current_y), simhei_font, color, bold)
                    # 更新x坐标
                    w, _ = self.draw.textbbox((0, 0), english_text, font=simhei_font)[2:4]
                    current_x += w
                    i = english_end
                # 处理其他字符
                else:
                    if faded:
                        _draw_char_with_faded_effect(char, (current_x, current_y), simhei_font, color, bold)
                    else:
                        self._draw_dot_matrix_text(char, (current_x, current_y), simhei_font, color, bold)
                    # 更新x坐标
                    w, _ = self.draw.textbbox((0, 0), char, font=simhei_font)[2:4]
                    current_x += w
                    i += 1
        
        # 定义内部函数来处理单个字符或字符串的消失效果
        def _draw_char_with_faded_effect(text, pos, font, color, bold):
            x, y = pos
            width, height = self.draw.textbbox((0, 0), text, font=font)[2:4]
            
            # 创建一个临时图像来绘制文字
            temp_img = Image.new('RGBA', (width, height), (255, 255, 255, 0))
            temp_draw = ImageDraw.Draw(temp_img)
            
            # 在临时图像上绘制文字
            temp_draw.text((0, 0), text, font=font, fill=color)
            
            # 创建一个与临时图像相同大小的数组
            pixels = np.array(temp_img)
            
            # 添加消失点和消失线效果（约10%的像素消失）
            # 随机选择10%的像素点设置为透明
            mask = np.random.random(pixels.shape[:2]) < 0.1
            pixels[mask] = [255, 255, 255, 0]
            
            # 添加一些垂直的消失线（模拟打印头损坏）
            num_lines = max(1, width // 30)  # 每30个像素宽度可能有一条线
            for _ in range(num_lines):
                line_x = np.random.randint(0, width)
                pixels[:, line_x, 3] = np.minimum(pixels[:, line_x, 3], np.random.randint(50, 150))
            
            # 将处理后的像素数组转回图像
            faded_img = Image.fromarray(pixels)
            
            # 将处理后的文字图像粘贴到原图像上
            self.image.paste(faded_img, (x, y), faded_img)
            
            # 如果需要加粗效果，添加额外的像素点
            if bold:
                directions = [(-1, -1), (-1, 0), (-1, 1),
                             (0, -1),          (0, 1),
                             (1, -1),  (1, 0), (1, 1)]
                for dx, dy in directions:
                    # 为加粗效果也添加消失效果
                    faded_bold_img = faded_img.copy()
                    # 降低加粗部分的不透明度
                    bold_pixels = np.array(faded_bold_img)
                    bold_pixels[:, :, 3] = bold_pixels[:, :, 3] // 2
                    faded_bold_img = Image.fromarray(bold_pixels)
                    self.image.paste(faded_bold_img, (x + dx, y + dy), faded_bold_img)
        
        # 将RGB颜色转换为RGBA，添加透明度
        if len(color) == 3:
            color = (*color, opacity)
        elif len(color) == 4:
            # 如果已经是RGBA格式，使用提供的透明度
            color = (color[0], color[1], color[2], opacity)
        
        # 调用混合文字绘制函数
        _draw_mixed_text(text, position, color, bold)
        
    def _draw_dot_matrix_text(self, text, position, font, color, bold):
        """绘制点阵风格的文字，模拟针式打印机效果"""
        x, y = position
        
        # 添加轻微的错位效果，模拟针式打印机的不精确性
        for i in range(2):
            offset_x = np.random.randint(-1, 2) if i > 0 else 0
            offset_y = np.random.randint(-1, 2) if i > 0 else 0
            self.draw.text((x + offset_x, y + offset_y), text, font=font, fill=color)
        
        # 如果需要加粗效果，在周围添加像素点
        if bold:
            directions = [(-1, -1), (-1, 0), (-1, 1),
                         (0, -1),          (0, 1),
                         (1, -1),  (1, 0), (1, 1)]
            for dx, dy in directions:
                self.draw.text((x + dx, y + dy), text, font=font, fill=color)
    
    def save_result(self, output_path='output.png'):
        """保存处理后的图片"""
        self.image.save(output_path)
        print(f"已保存输出图片: {output_path}")
        return output_path
    
    def preview(self):
        """预览图片"""
        self.image.show()
    
    def add_texts_from_array(self, texts_array):
        """
        从数组中批量添加文字
        
        参数:
        - texts_array: 包含多个文字配置的数组，每个配置为字典
        """
        for text_config in texts_array:
            # 提取配置参数，如果不存在则使用默认值
            text = text_config.get('text', '')
            position = text_config.get('position', (50, 50))
            font_size = text_config.get('font_size', 12)
            color = text_config.get('color', (0, 0, 0))
            opacity = text_config.get('opacity', 255)
            bold = text_config.get('bold', False)
            faded = text_config.get('faded', True)
            
            # 添加文字
            self.add_text(text, position, font_size, color, opacity, bold, faded)


def main():
    # 创建拟针式打印机实例
    printer = NeedlePrinter()
    
    # 示例：添加不同大小和位置的文字
    printer.add_text("资兴昊元贸易有", (2940, 552), font_size=44, color=(0, 0, 0, 160), opacity=120, faded=True)
    printer.add_text("石粉", (2976, 652), font_size=44, color=(0, 0, 0, 160), opacity=120, faded=True)
    printer.add_text("文素贞", (2976, 752), font_size=44, color=(0, 0, 0, 160), opacity=120, faded=True)



    printer.add_text("MS25090", (3060, 1146), font_size=44, color=(0, 0, 0, 80), opacity=80, faded=True)
    printer.add_text("2025/09/09", (3060, int((1146+1316)/2)), font_size=44, color=(0, 0, 0, 80), opacity=120, faded=True)
    printer.add_text("2025/09/09", (3060, 1316), font_size=44, color=(0, 0, 0, 80), opacity=80, faded=True)


    printer.add_text("湘L28992", (3060, 1518), font_size=44, color=(0, 0, 0, 80), opacity=80, faded=True)

    printer.add_text("48580", (3060, 1814), font_size=44, color=(0, 0, 0, 80), opacity=80, faded=True)
    printer.add_text("16080", (3060, 1914), font_size=44, color=(0, 0, 0, 80), opacity=80, faded=True)
    printer.add_text("32500", (3060, 2014), font_size=44, color=(0, 0, 0, 80), opacity=80, faded=True)



    
    # 保存结果
    output_path = printer.save_result()
    print(f"处理完成，输出文件: {output_path}")
    
    # 可选：预览图片
    # printer.preview()

if __name__ == '__main__':
    main()